#ifndef __OS_FILE_OP__
#define __OS_FILE_OP__

#include "os.h"

#if TARGET_OS==OS_WINDOWS

typedef HANDLE			hfile_t;
#define INVALID_HFILE	((hfile_t)-1)
#define IO_ERROR		((size_t)-1)

inline hfile_t create_file( const char * name, bool w, bool tmp )
{
	if( !name ) return INVALID_HFILE;
	DWORD dwAccess = GENERIC_READ | ( w ? GENERIC_WRITE : 0 );
	DWORD dwFlags = tmp ? (FILE_FLAG_DELETE_ON_CLOSE|FILE_ATTRIBUTE_TEMPORARY):0;
	HANDLE hFile = CreateFileA( name, dwAccess, 0, 0, CREATE_ALWAYS, dwFlags, 0 );
	if( hFile == INVALID_HANDLE_VALUE )
		return INVALID_HFILE;
	return hfile_t(hFile);
}

inline HRESULT seek_file( hfile_t f, INT64 dist, int sk )
{
	LARGE_INTEGER liDist; liDist.QuadPart = dist;
	LARGE_INTEGER liPos;
	if( !SetFilePointerEx( f, liDist, &liPos, sk ) )
		return E_FAIL;
	return S_OK;
}

inline size_t read_file( hfile_t f, void * buf, size_t cb )
{
	DWORD cbEff = 0;
	BOOL fok = ReadFile( f, buf, (DWORD)cb, &cbEff, 0 );
	if( !fok ) return IO_ERROR;
	return cbEff;
}

inline size_t write_file( hfile_t f, const void * buf, size_t cb )
{
	DWORD cbEff = 0;
	BOOL fok = WriteFile( f, buf, (DWORD)cb, &cbEff, 0 );
	if( !fok ) return IO_ERROR;
	return cbEff;
}

inline void close_file( hfile_t f )
{
	CloseHandle(f);
}

inline HRESULT set_file_end( hfile_t f, UINT64 off )
{
	RFAILED( seek_file( f, off, SEEK_SET ) );
	return SetEndOfFile(f) ? S_OK : E_FAIL;
}

#else


typedef int				hfile_t;
#define INVALID_HFILE	((hfile_t)-1)
#define IO_ERROR		((size_t)-1)

inline hfile_t create_file( const char * name, bool w, bool tmp )
{
	if( !name ) return INVALID_HFILE;
	int flags = w ? O_RDWR : O_RDONLY;
	flags |= O_CREAT|O_TRUNC;
	int f = open( name, flags, 00777 );
	if( f < 0 ) return INVALID_HFILE;
	if( tmp ) unlink(name);
	return hfile_t(f);
}

inline HRESULT seek_file( hfile_t f, INT64 dist, int sk )
{
#ifdef _LARGEFILE64_SOURCE
	off64_t ptr = lseek64( f, (off64_t)dist, sk );
	if( ptr < 0 ) return E_FAIL;
#else
	LARGE_INTEGER liDist;
	liDist.QuadPart = dist;
	loff_t result = 0;
	int i = _llseek( f, liDist.u.HighPart, liDist.u.LowPart, &result, sk );
	if( i < 0 ) return E_FAIL;
#endif
	return S_OK;
}

inline size_t read_file( hfile_t f, void * buf, size_t cb )
{
	int r = read( f, buf, cb );
	if( r < 0 ) return IO_ERROR;
	return r;
}

inline size_t write_file( hfile_t f, const void * buf, size_t cb )
{
	int w = write( f, buf, cb );
	if( w < 0 ) return IO_ERROR;
	return w;
}

inline void close_file( hfile_t f )
{
	close(f);
}

inline HRESULT set_file_end( hfile_t f, UINT64 off )
{
#ifdef _LARGEFILE64_SOURCE
	return ftruncate64( f, off );
#else
	return ftruncate( f, off );
#endif
}

#endif

#endif